﻿#include<vector>
#include<string>
#include<iostream>

using namespace std;

enum State
{
	EXIST,
	EMPTY,
	DELETE
};

template<class K>
struct HashFunc
{
	size_t operator()(const K& key)
	{
		return size_t(key);
	}
};

template<>//偏特化处理string类传参
struct HashFunc<string>
{
	size_t operator()(const string& s)
	{
		size_t hash = 0;
		for (auto ch : s)
		{
			hash += ch;
			hash *= 131;//相乘减少冲突概率
		}
		return hash;
	}
};


struct StringHashFunc
{
	size_t operator()(const string& s)
	{
		size_t hash = 0;
		for (auto ch : s)//把所有字符的ascii值加起来比较，尽量减少冲突
		{
			hash += ch;
		}
		return hash;
	}
};

template<class K, class V>
struct HashData
{
	pair<K, V> _kv;
	State _state = EMPTY;
};

namespace open_address//开放定址法 
{
	template<class K, class V, class Hash = HashFunc<K>>//hash代表仿函数
	class HashTable
	{
	public:
		HashTable() :_tables(11), _n(0)
		{}

		inline unsigned long __stl_next_prime(unsigned long n)
		{
			// Note: assumes long is at least 32 bits.
			static const int __stl_num_primes = 28;
			static const unsigned long __stl_prime_list[__stl_num_primes] =
			{
				53,97,193,389,769,1543,3079,6151,12289,
				24593,49157,98317,196613,393241,786433,1572869,
				3145739,6291469,12582917, 25165843,
				50331653,100663319, 201326611, 402653189, 805306457,
				1610612741, 3221225473, 4294967291
			};
			const unsigned long* first = __stl_prime_list;
			const unsigned long* last = __stl_prime_list + __stl_num_primes;
			const unsigned long* pos = lower_bound(first, last, n);
			return pos == last ? *(last - 1) : *pos;
		}

		bool Insert(const pair<K, V>& kv)
		{
			//除法散列法进行线性探测
			if (Find(kv.first))
				return false;
			if (_n * 10 / _tables.size() >= 7)//负载因子大于等于0.7进行扩容
			{
				//vector<HashData<K, V>> newtables(_tables.size() * 2);//扩容后M改变，全部重新插入
				//for (auto& data : tables)
				//{
				//	//旧表数据映射新表
				//	if (data._state == EXIST)
				//	{
				//		size_t hash0 = data._kv.first % newtables.size();
				//		size_t hashi = hash0;
				//		size_t i = 1;
				//		//。。。
				//	}
				//}
				//_tables.swap(newtables._tables);

				HashTable<K, V, Hash> newht;
				newht._tables.resize(__stl_next_prime(_tables.size()));
				for (auto& data : _tables)
				{
					//旧表数据映射新表
					if (data._state == EXIST)
					{
						newht.Insert(data._kv);
					}
				}
				_tables.swap(newht._tables);
			}

			Hash hash;
			size_t hash0 = hash(kv.first) % _tables.size();
			size_t hashi = hash0;
			size_t i = 1;

			while (_tables[hashi]._state == EXIST)
			{
				//线性探测
				hashi = (hash0 + i) % _tables.size();//防止越界
				++i;
			}

			_tables[hashi]._kv = kv;
			_tables[hashi]._state = EXIST;
			++_n;
			return true;
		}

		HashData<K, V>* Find(const K& key)
		{
			Hash hs;
			size_t hash0 = hs(key) % _tables.size();
			size_t hashi = hash0;
			size_t i = 1;
			while (_tables[hashi]._state != EMPTY)
			{
				if (_tables[hashi]._kv.first == key && _tables[hashi]._state == EXIST)
				{
					return &_tables[hashi];
				}

				//线性探测
				hashi = (hash0 + i) % _tables.size();
				++i;
			}
			return nullptr;
		}

		bool erase(const K& key)
		{
			HashData<K, V>* ret = Find(key);
			if (ret)
			{
				ret->_state = DELETE;
				return true;
			}
			else
			{
				return false;
			}
		}
	private:
		vector<HashData<K, V>> _tables;
		size_t _n = 0; // 表中存储数据个数
	};
}

namespace hash_bucket//桶（链地址法）
{
	template<class K, class V>
	struct HashNode
	{
		pair<K, V> _kv;
		HashNode<K, V>* _next;
		HashNode(const pair<K, V>& kv)
			:_kv(kv)
			, _next(nullptr)
		{}
	};
	template<class K, class V, class Hash = HashFunc<K>>
	class HashTable
	{
		typedef HashNode<K, V> Node;
		inline unsigned long __stl_next_prime(unsigned long n)
		{
			static const int __stl_num_primes = 28;
			static const unsigned long __stl_prime_list[__stl_num_primes] =
			{
			53,	97,193,389,769,1543,
			3079,6151,12289,24593,49157,
			98317,196613,393241,786433,1572869,
			3145739,6291469,12582917, 25165843,
			50331653,100663319, 201326611, 402653189, 805306457,
			1610612741, 3221225473, 4294967291
			};
			const unsigned long* first = __stl_prime_list;
			const unsigned long* last = __stl_prime_list +
				__stl_num_primes;
			const unsigned long* pos = lower_bound(first, last, n);
			return pos == last ? *(last - 1) : *pos;
		}
	public:
		HashTable()
		{
			_tables.resize(__stl_next_prime(_tables.size()), nullptr);
		}
		// 拷⻉构造和赋值拷⻉需要实现深拷⻉，有兴趣的同学可以⾃⾏实现~HashTable()
		~HashTable()
		{
			// 依次把每个桶释放
			for (size_t i = 0; i < _tables.size(); i++)
			{
				Node* cur = _tables[i];
				while (cur)
				{
					Node* next = cur->_next;
					delete cur;
					cur = next;
				}
				_tables[i] = nullptr;
			}
		}
		bool Insert(const pair<K, V>& kv)
		{
			Hash hs;
			size_t hashi = hs(kv.first) % _tables.size();
			// 负载因⼦==1扩容
			if (_n == _tables.size())
			{
				/*HashTable<K, V> newHT;
				newHT._tables.resize(_tables.size() * 2);
				for (size_t i = 0; i < _tables.size(); i++)
				{
				Node* cur = _tables[i];
				while(cur)
				{
				newHT.Insert(cur->_kv);
				cur = cur->_next;
				}
				}
				_tables.swap(newHT._tables);*/
				// 这⾥如果使⽤上⾯的⽅法，扩容时创建新的结点，后⾯还要使⽤就结
				//点，浪费了下⾯的⽅法，直接移动旧表的结点到新表，效率更好
				vector<Node*> newtables(__stl_next_prime(_tables.size()), nullptr);
				for (size_t i = 0; i < _tables.size(); i++)
				{
					Node* cur = _tables[i];
					while (cur)
					{
						Node* next = cur->_next;
						// 旧表中节点，挪动新表重新映射的位置
						size_t hashi = hs(cur->_kv.first) % newtables.size();
						// 头插到新表
						cur->_next = newtables[hashi];
						newtables[hashi] = cur;
						cur = next;
					}
					_tables[i] = nullptr;
				}
				_tables.swap(newtables);
			}
			// 头插
			Node* newnode = new Node(kv);
			newnode->_next = _tables[hashi];
			_tables[hashi] = newnode;
			++_n;
			return true;
		}

		Node* Find(const K& key)
		{
			Hash hs;
			size_t hashi = hs(key) % _tables.size();
			Node* cur = _tables[hashi];
			while (cur)
			{
				if (cur->_kv.first == key)
				{
					return cur;
				}
				cur = cur->_next;
			}
			return nullptr;
		}

		bool Erase(const K& key)
		{
			Hash hs;
			size_t hashi = hs(key) % _tables.size();
			Node* prev = nullptr;
			Node* cur = _tables[hashi];
			while (cur)
			{
				if (cur->_kv.first == key)
				{
					if (prev == nullptr)
					{
						_tables[hashi] = cur->_next;
					}
					else
					{
						prev->_next = cur->_next;
					}
					delete cur;
					--_n;
					return true;
				}
				prev = cur;
				cur = cur->_next;
			}
			return false;
		}
private:
	vector<Node*> _tables; // 指针数组
	size_t _n = 0;
	// 表中存储数据个数
};
}